#include "raylib.h"
#include "raymath.h"
#include <math.h>

// 2D线段相交检测
bool CheckLineIntersection(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, Vector2* intersection)
{
    float denominator = ((p2.x - p1.x) * (p4.y - p3.y) - (p2.y - p1.y) * (p4.x - p3.x));
    
    if (fabs(denominator) < 0.0001f) return false; // 平行
    
    float ua = ((p4.x - p3.x) * (p1.y - p3.y) - (p4.y - p3.y) * (p1.x - p3.x)) / denominator;
    float ub = ((p2.x - p1.x) * (p1.y - p3.y) - (p2.y - p1.y) * (p1.x - p3.x)) / denominator;
    
    if (ua >= 0 && ua <= 1 && ub >= 0 && ub <= 1) {
        if (intersection) {
            intersection->x = p1.x + ua * (p2.x - p1.x);
            intersection->y = p1.y + ua * (p2.y - p1.y);
        }
        return true;
    }
    
    return false;
}

// 2D光线投射，找到最近的碰撞点
Vector2 Cast2DRay(Vector2 start, Vector2 direction, Rectangle *walls, int wallCount, float maxDistance, bool* hit)
{
    Vector2 end = Vector2Add(start, Vector2Scale(Vector2Normalize(direction), maxDistance));
    Vector2 closestHit = end;
    float closestDistance = maxDistance;
    *hit = false;
    
    for (int i = 0; i < wallCount; i++) {
        Rectangle wall = walls[i];
        
        // 墙壁的四条边
        Vector2 edges[4][2] = {
            {{wall.x, wall.y}, {wall.x + wall.width, wall.y}}, // 上边
            {{wall.x, wall.y + wall.height}, {wall.x + wall.width, wall.y + wall.height}}, // 下边
            {{wall.x, wall.y}, {wall.x, wall.y + wall.height}}, // 左边
            {{wall.x + wall.width, wall.y}, {wall.x + wall.width, wall.y + wall.height}}  // 右边
        };
        
        for (int j = 0; j < 4; j++) {
            Vector2 intersection;
            if (CheckLineIntersection(start, end, edges[j][0], edges[j][1], &intersection)) {
                float distance = Vector2Distance(start, intersection);
                if (distance < closestDistance) {
                    closestDistance = distance;
                    closestHit = intersection;
                    *hit = true;
                }
            }
        }
    }
    
    return closestHit;
}

int main(void)
{
    const int screenWidth = 800;
    const int screenHeight = 600;
    InitWindow(screenWidth, screenHeight, "纯2D手电筒迷宫");
    
    // 迷宫墙壁
    Rectangle walls[] = {
        {50, 50, 700, 20}, {50, 530, 700, 20},
        {50, 50, 20, 500}, {730, 50, 20, 500},
        {150, 150, 200, 20}, {400, 200, 20, 150},
        {250, 300, 150, 20}, {500, 350, 200, 20},
        {200, 400, 20, 100}, {600, 150, 20, 200},
        {300, 100, 20, 80}
    };
    int wallCount = sizeof(walls) / sizeof(walls[0]);
    
    Vector2 playerPos = {400, 300};
    float playerSpeed = 3.0f;
    float flashlightRadius = 200.0f;
    
    // 创建光照纹理
    RenderTexture2D lightTexture = LoadRenderTexture(screenWidth, screenHeight);
    
    SetTargetFPS(60);
    
    while (!WindowShouldClose())
    {
        // 玩家移动
        if (IsKeyDown(KEY_W)) playerPos.y -= playerSpeed;
        if (IsKeyDown(KEY_S)) playerPos.y += playerSpeed;
        if (IsKeyDown(KEY_A)) playerPos.x -= playerSpeed;
        if (IsKeyDown(KEY_D)) playerPos.x += playerSpeed;
        
        // 边界检查
        playerPos.x = fmax(60, fmin(740, playerPos.x));
        playerPos.y = fmax(60, fmin(540, playerPos.y));
        
        Vector2 mousePos = GetMousePosition();
        
        BeginDrawing();
        ClearBackground(BLACK);
        
        // 第一步：绘制光照效果
        BeginTextureMode(lightTexture);
            ClearBackground(BLACK);
            
            // 手电筒参数
            Vector2 toMouse = Vector2Subtract(mousePos, playerPos);
            float baseAngle = atan2f(toMouse.y, toMouse.x);
            float fov = 70.0f * DEG2RAD; // 70度视野
            int rays = 80;
            
            // 绘制光锥
            for (int i = 0; i <= rays; i++) {
                float angle = baseAngle - fov/2 + (fov * i / rays);
                Vector2 rayDir = {cosf(angle), sinf(angle)};
                
                bool hit;
                Vector2 hitPoint = Cast2DRay(playerPos, rayDir, walls, wallCount, flashlightRadius, &hit);
                
                // 绘制单条光线
                int steps = 30;
                for (int s = 0; s <= steps; s++) {
                    float t = (float)s / steps;
                    Vector2 point;
                    
                    if (hit) {
                        point = Vector2Lerp(playerPos, hitPoint, t);
                    } else {
                        point = Vector2Add(playerPos, Vector2Scale(rayDir, flashlightRadius * t));
                    }
                    
                    // 强度计算
                    float distance = Vector2Distance(playerPos, point);
                    float intensity = 1.0f - (distance / flashlightRadius);
                    intensity *= intensity; // 二次衰减
                    
                    // 角度衰减
                    float angleDiff = fabsf(angle - baseAngle);
                    float angleAttenuation = 1.0f - (angleDiff / (fov/2));
                    
                    Color lightColor = {
                        255, 255, 200,
                        (unsigned char)(255 * intensity * angleAttenuation)
                    };
                    
                    if (s == 0) {
                        DrawCircleV(point, 3, lightColor);
                    } else {
                        DrawPixelV(point, lightColor);
                    }
                }
            }
            
            // 中心光斑
            DrawCircleGradient(playerPos.x, playerPos.y, 25, 
                              (Color){255, 255, 220, 180}, 
                              (Color){255, 255, 220, 0});
                              
        EndTextureMode();
        
        // 第二步：绘制墙壁（只在光照下可见）
        for (int i = 0; i < wallCount; i++) {
            // 简单可见性检查：检查墙壁中心是否可见
            Vector2 wallCenter = {
                walls[i].x + walls[i].width / 2,
                walls[i].y + walls[i].height / 2
            };
            
            bool hit;
            Vector2 hitPoint = Cast2DRay(playerPos, 
                Vector2Subtract(wallCenter, playerPos), 
                walls, wallCount, flashlightRadius, &hit);
            
            float distanceToHit = Vector2Distance(playerPos, hitPoint);
            float distanceToWall = Vector2Distance(playerPos, wallCenter);
            
            // 如果墙壁在光线范围内且没有被阻挡
            if (!hit || distanceToHit >= distanceToWall - 10) {
                DrawRectangleRec(walls[i], GRAY);
                
                // 墙壁边框
                DrawRectangleLinesEx(walls[i], 2, DARKGRAY);
            }
        }
        
        // 绘制玩家
        DrawCircleV(playerPos, 10, BLUE);
        DrawCircleV(playerPos, 6, SKYBLUE);
        
        // 绘制手电筒方向线
        DrawLineV(playerPos, Vector2Add(playerPos, Vector2Scale(Vector2Normalize(toMouse), 30)), YELLOW);
        
        // 第三步：应用光照效果
        BeginBlendMode(BLEND_ADDITIVE);
        DrawTextureRec(lightTexture.texture, 
                      (Rectangle){0, 0, (float)lightTexture.texture.width, (float)-lightTexture.texture.height},
                      (Vector2){0, 0}, WHITE);
        EndBlendMode();
        
        // UI
        DrawText("WASD: 移动", 10, 10, 20, GREEN);
        DrawText("鼠标控制手电筒方向", 10, 35, 20, GREEN);
        DrawText("纯2D光线遮挡 - 光线不能穿墙", 10, 60, 20, YELLOW);
        
        EndDrawing();
    }
    
    UnloadRenderTexture(lightTexture);
    CloseWindow();
    
    return 0;
}